package cn.zy.amyan.client.future;


import cn.zy.amyan.core.base.RequestData;
import cn.zy.amyan.core.base.ResponseData;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

/**
 * @author 子言
 * @date 2024/5/1 下午 16:45
 */
public class AyFutureResponse implements Future<ResponseData> {

	// 存储requestId与AyFutureResponse对象的映射关系
	private static final Map<String, AyFutureResponse> MAP = new ConcurrentHashMap<>();

	//是否处理完成，默认为false
	private boolean done = false;
	//定义⼀个对象⽤于锁操作
	private final Object lock = new Object();
	//响应对象
	private ResponseData response;

	/**
	 * 在构造函数中将当前对象存储到MAP中
	 *
	 * @param request
	 */
	public AyFutureResponse(RequestData request) {
		MAP.put(request.getRequestId(), this);
	}

	public static AyFutureResponse getAyFutureResponse(String requestId) {
		return MAP.get(requestId);
	}

	@Override
	public boolean cancel(boolean mayInterruptIfRunning) {
		return false;
	}

	@Override
	public boolean isCancelled() {
		return false;
	}

	@Override
	public boolean isDone() {
		return done;
	}

	@Override
	public ResponseData get() throws InterruptedException, ExecutionException {
		return this.get(-1, TimeUnit.MILLISECONDS);
	}

	@Override
	public ResponseData get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException {
		if (isDone()) {
			return this.response;
		}
		// 确保只有⼀个线程在⼀个时刻执⾏操作
		synchronized (lock) { 
			try {
				// 如果没有设置超时时间的话，就⼀直等待
				if (timeout < 0) { 
					lock.wait();
				} else {
					// 如果设置了超时时间的话，就在给定时间内进⾏等待
					long timeoutMillis = (TimeUnit.MILLISECONDS == unit) ?
							                     timeout : TimeUnit.MILLISECONDS.convert(timeout, unit);
					lock.wait(timeoutMillis);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		if (isDone()) {
			return this.response;
		}
		throw new RuntimeException("获取数据，等待超时。。。");
	}

	public void setResponse(ResponseData response){
		this.response = response;
		//确保只有⼀个线程在⼀个时刻执⾏操作
		synchronized (lock) { 
			this.done = true;
			//唤醒等待的线程
			this.lock.notifyAll(); 
		}
		//删除已缓存的对象
		MAP.remove(response.getRequestId());
	}
}
